package com.framework.loippi.controller.admin;

import com.framework.loippi.cache.ConfigCache;
import com.framework.loippi.controller.GenericController;
import com.framework.loippi.entity.*;
import com.framework.loippi.service.*;
import com.framework.loippi.support.Message;
import com.framework.loippi.support.Pageable;
import com.loippi.core.gen.IFactory;
import com.loippi.core.gen.ITable;
import com.loippi.core.gen.mysql.impl.MysqlFactory;
import com.qiniu.util.Auth;
import com.qiniu.util.StringMap;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.ServletContextAware;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.ServletContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.sql.SQLException;
import java.util.*;


/**
 * Controller - 共用
 *
 * @author Loippi Team
 * @version 1.0
 */
@Controller("adminCommonController")
@RequestMapping("/admin/common")
public class CommonController extends GenericController implements ServletContextAware {

    @Value("${system.name}")
    private String systemName;
    @Value("${system.version}")
    private String systemVersion;
    @Value("${system.description}")
    private String systemDescription;

    @Resource
    private AclService aclService;

    @Resource
    private AreaService areaService;

    @Resource
    private UserService userService;

    @Resource
    private RedisService redisService;

    @Resource(name = "captchaServiceImpl")
    private CaptchaService captchaService;

    @Resource
    private DoctorService doctorService;

    @Resource
    private ImUserService imUserService;

    @Resource
    private PatientService patientService;


    /**
     * servletContext
     */
    private ServletContext servletContext;

    public void setServletContext(ServletContext servletContext) {
        this.servletContext = servletContext;
    }

    @Resource
    private FileService fileService;

    /**
     * 主页
     */

    @RequestMapping(value = "/main", method = RequestMethod.GET)
    public String main(HttpServletRequest request, ModelMap model) {

        model.addAttribute("systemName", systemName);
        model.addAttribute("systemVersion", systemVersion);
        model.addAttribute("systemDescription", systemDescription);
        model.addAttribute("javaVersion", System.getProperty("java.version"));
        model.addAttribute("javaHome", System.getProperty("java.home"));
        model.addAttribute("osName", System.getProperty("os.name"));
        model.addAttribute("osArch", System.getProperty("os.arch"));
        model.addAttribute("serverInfo", servletContext.getServerInfo());
        model.addAttribute("servletVersion", servletContext.getMajorVersion() + "." + servletContext.getMinorVersion());
        Subject subject = SecurityUtils.getSubject();
        List<Acl> acls = null;

        if (subject != null) {
            Principal principal = (Principal) subject.getPrincipal();
            if (principal != null && principal.getId() != null) {
                model.addAttribute("principal", principal);
                // 根据登录人角色查询对应的菜单
                User user = userService.find(principal.getId());
                model.addAttribute("user", user);
                acls = aclService.findByRoleIdSelf(user.getRoleId());
            }
        } else {
            acls = aclService.findRoots();
        }
//        List<Acl> acls = aclService.findRoots()

        Map map = new HashMap();
        map.put("order", "PARENT_ID,sorts");
        List<Acl> allAcls = aclService.findByParams(map);
        for (Acl acl : acls) {
            acl.getChildren().addAll(this.getChildrens(allAcls, acl.getId()));
        }
        model.addAttribute("acls", acls);
        User user = userService.getCurrent();
        if (user != null && user.getTheme() != null && user.getTheme() == 2) {
            return "/admin/common/main_classic";
        }
        return "/admin/common/main";
    }

    private List<Acl> getChildrens(List<Acl> allAcls, Long pId) {

        List<Acl> childrens = new ArrayList();
        for (Iterator iterator = allAcls.iterator(); iterator.hasNext(); ) {
            Acl acl = (Acl) iterator.next();
            if (pId.equals(acl.getParentId())) {
                childrens.add(acl);
            }
        }
        return childrens;
    }

    /**
     * 主题设置
     */

    @RequestMapping(value = "/theme", method = RequestMethod.POST)
    public @ResponseBody
    Message theme(HttpServletRequest request, Integer theme, ModelMap model) {
        User user = userService.getCurrent();
        user.setTheme(theme);
        userService.update(user);
        return SUCCESS_MESSAGE;
    }


    /**
     * 首页
     */
    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public String index(Pageable pageable, ModelMap model) {


        model.addAttribute("systemName", systemName);
        model.addAttribute("systemVersion", systemVersion);
        model.addAttribute("systemDescription", systemDescription);
        model.addAttribute("javaVersion", System.getProperty("java.version"));
        model.addAttribute("javaHome", System.getProperty("java.home"));
        model.addAttribute("osName", System.getProperty("os.name"));
        model.addAttribute("osArch", System.getProperty("os.arch"));
        model.addAttribute("serverInfo", servletContext.getServerInfo());
        model.addAttribute("servletVersion", servletContext.getMajorVersion() + "." + servletContext.getMinorVersion());

        return "/admin/common/index";
    }


    /**
     * 注销
     */
    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    public String execute(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
        SecurityUtils.getSubject().logout();
        return "redirect:/admin/login.jhtml?jssionid=" + session.getId();
    }


    /**
     * 数据字典
     */
    @RequestMapping(value = "/dic", method = RequestMethod.GET)
    public String dic(ModelMap model) {
        try {
            IFactory factory = MysqlFactory.getInstance(ConfigCache.getConfig("jdbc.url"), ConfigCache.getConfig("jdbc.username"), ConfigCache.getConfig("jdbc.password"));
            List<ITable> tables = factory.getTables();
            model.addAttribute("tables", tables);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return "/admin/common/dic";
    }


    /**
     * 地区
     */
    @RequestMapping(value = "/area", method = RequestMethod.GET)
    public @ResponseBody
    Map<Long, String> area(Long parentId) {
        List<Area> areas = new ArrayList<Area>();
        if (parentId != null) {
            areas = areaService.findChildrens(parentId);
        } else {
            areas = areaService.findRoots();
        }
        Map<Long, String> options = new HashMap<Long, String>();
        for (Area area : areas) {
            options.put(area.getId(), area.getName());
        }
        return options;
    }

    /**
     * 验证码
     */
    @RequestMapping(value = "/captcha", method = RequestMethod.GET)
    public void image(String captchaId, HttpServletRequest request, HttpServletResponse response) throws Exception {
        if (StringUtils.isEmpty(captchaId)) {
            captchaId = request.getSession().getId();
        }
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setHeader("Cache-Control", "no-store");
        response.setDateHeader("Expires", 0);
        response.setContentType("image/jpeg");

        ServletOutputStream servletOutputStream = null;
        try {
            servletOutputStream = response.getOutputStream();
            BufferedImage bufferedImage = captchaService.buildImage(captchaId);
            ImageIO.write(bufferedImage, "jpg", servletOutputStream);
            servletOutputStream.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(servletOutputStream);
        }
    }

    /**
     * 错误提示
     */
    @RequestMapping("/error")
    public String error() {
        return ERROR_VIEW;
    }

    /**
     * 权限错误
     */
    @RequestMapping("/unauthorized")
    public String unauthorized(HttpServletRequest request,
                               HttpServletResponse response) {
        String requestType = request.getHeader("X-Requested-With");
        if (requestType != null
                && requestType.equalsIgnoreCase("XMLHttpRequest")) {
            response.addHeader("loginStatus", "unauthorized");
            try {
                response.sendError(HttpServletResponse.SC_FORBIDDEN);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
        return "/admin/common/unauthorized";
    }

    /**
     * 资源不存在
     */
    @RequestMapping("/resource_not_found")
    public String resourceNotFound() {
        return "/admin/common/resource_not_found";
    }


    @RequestMapping("/ueditor_config")
    public String ueditorConfig(HttpServletRequest request, ModelMap model) {
        String qiniuUrl = ConfigCache.getConfig("qiniu.url");
        model.addAttribute("qiniuUrl", qiniuUrl);
        model.addAttribute("qiniuTokenUrl", request.getContextPath() + "/admin/common/qiniu_token.jhtml");
        return "/admin/common/ueditor_config";
    }

    @RequestMapping("/qiniu_token")
    @ResponseBody
    public Map<String, String> qiniuToken(ModelMap model) {

        Auth auth = Auth.create(ConfigCache.getConfig("qiniu.accessKey"), ConfigCache.getConfig("qiniu.secretKey"));
        StringMap policy = new StringMap();
        policy.put("returnBody", "{\"state\": \"SUCCESS\",\"url\": \"${key}\",\"source\": \"" + ConfigCache.getConfig("qiniu.url") + "${key}\"}");
        String token = auth.uploadToken(ConfigCache.getConfig("qiniu.bucket"), null, 30 * 60L, policy);

        Map<String, String> result = new HashMap<>();
        result.put("token", token);

        return result;
    }

    // 跳转聊天界面
    @RequestMapping(value = "/chat", method = RequestMethod.GET)
    public String chat(Model model) {
        Subject subject = SecurityUtils.getSubject();
        if (subject != null) {
            Principal principal = (Principal) subject.getPrincipal();
            if (principal != null && principal.getId() != null) {
                model.addAttribute("principal", principal);
                // 如果是医生登录，则同时登录到im
                if (principal.getRolename().equals("doctor")) {
                    User user = userService.getCurrent();
                    Doctor doctor = doctorService.findByPhone(user.getUsername());
                    ImUser imUser = imUserService.find((long)doctor.getImUserId());
                    model.addAttribute("doctor", doctor);
                    model.addAttribute("imUser", imUser);
                    List<ImUser> list = imUserService.findAll();
                    model.addAttribute("imUsers", list);
                }
            }
        }
        return "/admin/common/chat";
    }


    @PostMapping("/addExplains")
    public boolean addExplains(Long imUserId, String explains){
        Patient patient = patientService.getPatientByImUserId(imUserId);
        // 是否存在患者
        // 更新患者诊断信息
        patient.setExplains(explains);
        Long test=patientService.update(patient);
        return patientService.update(patient)>0L;
    }

}